﻿using System;
using System.Configuration;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;
using LegoBotPrimaAbstractions;

namespace LegoBotPrimaUI
{
    /// <summary>
    /// Interaction logic for PrimaMainWindow.xaml
    /// </summary>
    public partial class MainPrimaWindow : Window, IMainPrimaWindow
    {
        

        private const string ACTION_STOP = "LegoBotPrima.Actions.StopBotAction, LegoBotPrimaService.Y2010.M06";
        private const string ACTION_FORWARD = "LegoBotPrima.Actions.ForwardBotAction, LegoBotPrimaService.Y2010.M06";
        private const string ACTION_LEFT = "LegoBotPrima.Actions.LeftBotAction, LegoBotPrimaService.Y2010.M06";
        private const string ACTION_RIGHT = "LegoBotPrima.Actions.RightBotAction, LegoBotPrimaService.Y2010.M06";
        private const string ACTION_BACKWARD = "LegoBotPrima.Actions.BackwardBotAction, LegoBotPrimaService.Y2010.M06";
        private const string ACTION_START_MANUAL = "LegoBotPrima.Actions.StartManualBotAction, LegoBotPrimaService.Y2010.M06";
        private const string ACTION_START_AUTONOMOUS = "LegoBotPrima.Actions.StartAutonomousBotAction, LegoBotPrimaService.Y2010.M06";


        private readonly RotateTransform _botRotation;
        private readonly ScaleTransform _irDistanceBeam;
        private readonly TranslateTransform _linesShift;

        public MainPrimaWindow()
        {
            InitializeComponent();

            this.BotCanvas.RenderTransform = this._botRotation = new RotateTransform { CenterX = 0, CenterY = 0 };
            this.Distance.RenderTransform = this._irDistanceBeam = new ScaleTransform { CenterX = 20, CenterY = 20 };
            this.LinesCanvas.RenderTransform = this._linesShift = new TranslateTransform();

            this.DrawLines();
        }
            

        public MainPrimaWindow(ILegoBotPrimaService service) : this()
        {
            Service = service;
        }

        public ILegoBotPrimaService Service { get; private set; }


        private void DrawLines()
        {
            var color = UiUtil.ToColor("#AAAAAA");
            for (int i = 0; i < 80; i++)
            {
                var num = i*25;
                var horz = new Line { Stroke = new SolidColorBrush(color), X1 = 0, X2 = 2000, Y1 = num, Y2 = num };
                var vert = new Line { Stroke = new SolidColorBrush(color), X1 = num, X2 = num, Y1 = 0, Y2 = 2000 };
                this.LinesCanvas.Children.Add(horz);
                this.LinesCanvas.Children.Add(vert);
            }

            this._linesShift.X -= 1000;
            this._linesShift.Y -= 1015;
        }


        private void DrawBotAngleOnMapUI(double rotationAngle)
        {
            this._botRotation.Angle = (rotationAngle + 90) % 360;
        }
        private void DrawBotPositionChangeOnMapUI(double xChange, double yChange)
        {
            this._linesShift.X -= xChange;
            this._linesShift.Y -= yChange;
        }
        private void DrawDistanceOnMapUI(int distance)
        {
            this._irDistanceBeam.ScaleY = (distance / 255.0) * 9.5 + 0.5;
        }


        #region IMainPrimaWindow


        public int CanvasWidth { get { return 1000; } }
        public int CanvasHeight { get { return 1000; } }

        public void DrawBotAngleOnMap(double rotationAngle)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, 
                                new Action<double>(this.DrawBotAngleOnMapUI), rotationAngle);
        }
        public void DrawBotPositionChangeOnMap(double xChange, double yChange)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal,
                              new Action<Point>(p => this.DrawBotPositionChangeOnMapUI(p.X, p.Y)),
                              new Point(xChange, yChange));
        }

        public void DrawDistanceOnMap(int distance)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal,
                                new Action<int>(this.DrawDistanceOnMapUI), distance);
        }

        public void SetUltrasonic(int cm)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, 
                                new Action<string>(text => this.UltrasonicText.Text = text), cm.ToString());
        }
        public void SetCompass(double degrees)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, 
                                new Action<string>(text => this.CompassText.Text = text), degrees.ToString());
        }
        public void SetBumper(string bumperName, bool isOn)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal,
                                new Action<string>(text =>
                                                       {
                                                           this.Bumper.Visibility = (text == "Bumper PRESSED") ? Visibility.Visible : Visibility.Collapsed;
                                                           this.BumperText.Text = text;
                                                       }), 
                                                       bumperName + (isOn ? " PRESSED" : " RELEASED"));
        }
        public void SetBotActionType(IBotAction action)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, 
                                new Action<Type>(bat =>
                                {
                                    this.BotActionText.Text = bat.Name.Replace("BotAction", "");
                                    if (!this.BotActionsList.IsEnabled)
                                        return;
                                    foreach (ComboBoxItem item in
                                        from ComboBoxItem item in this.BotActionsList.Items
                                        let curr = Type.GetType(item.Tag.ToString())
                                        where bat == curr
                                        select item)
                                    {
                                        item.IsSelected = true;
                                        return;
                                    }
                                }), action.GetType());
        }

        public void SetEnabled()
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, 
                                new Action(()=>
                                {
                                    this.StartAutonomousButton.IsEnabled = true;
                                    this.StartManualButton.IsEnabled = true;
                                }));
        }

        public void Error(string message)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal,
                                new Action(() => MessageBox.Show("ERROR: " + message)));
        }
        
        #endregion


        private void StartAutonomousButton_Click(object sender, RoutedEventArgs e)
        {
            ExecuteBotActionByTypeName(ACTION_START_AUTONOMOUS);
            StopButton.IsEnabled = true;
            EnableManualButtons(false);
        }
        private void StartManualButton_Click(object sender, RoutedEventArgs e)
        {
            ExecuteBotActionByTypeName(ACTION_START_MANUAL);
            StopButton.IsEnabled = true;
            EnableManualButtons(true);
        }
        private void StopButton_Click(object sender, RoutedEventArgs e)
        {
            ExecuteBotActionByTypeName(ACTION_STOP);
            StopButton.IsEnabled = false;
            EnableManualButtons(false);
            StartManualButton.IsEnabled = true;
            StartAutonomousButton.IsEnabled = true;
        }
        private void LeftButton_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ExecuteBotActionByTypeName(ACTION_LEFT);
        }
        private void ForwardButton_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ExecuteBotActionByTypeName(ACTION_FORWARD);
        }
        private void RightButton_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ExecuteBotActionByTypeName(ACTION_RIGHT);
        }
        private void BackwardButton_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ExecuteBotActionByTypeName(ACTION_BACKWARD);
        }
        private void StopMovement(object sender, MouseButtonEventArgs buttonEventArgs)
        {
            ExecuteBotActionByTypeName(((ListBoxItem)BotActionsList.SelectedValue).Tag.ToString());
        }




        private void EnableManualButtons(bool enable)
        {
            ForwardButton.IsEnabled = enable;
            LeftButton.IsEnabled = enable;
            RightButton.IsEnabled = enable;
            BackwardButton.IsEnabled = enable;
            BotActionsList.IsEnabled = enable;

            StartAutonomousButton.IsEnabled = enable;
            StartManualButton.IsEnabled = !enable;
        }

        private void BotActionsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!BotActionsList.IsEnabled) return;

            ExecuteBotActionByTypeName(((ListBoxItem)BotActionsList.SelectedValue).Tag.ToString());
        }

        private void ExecuteBotActionByTypeName(string typeName)
        {
            var type = Type.GetType(typeName);

            var action = (IBotAction)Activator.CreateInstance(type);

            Service.ExecuteBotAction(action);
        }

    }
}